﻿using System.Linq;
using Autofac;
using log4net;
using PortableVersion.Core;
using PortableVersion.Core.FileSystem;
using PortableVersion.Core.FileSystem.Pvml;
using PortableVersion.Core.FileSystem.Services;
using PortableVersion.Core.SourceControl;

namespace PortableVersion.BootStapper
{
    internal static class Builder
    {
        internal static IContainer GetContainer()
        {
            var builder = new ContainerBuilder();
            builder.Register(c => new ConfigurationProvider())
                .As<IConfigurationProvider>()
                .SingleInstance();
            builder.Register((c, p) => new FileVersioningSource(p.Named<string>("path"),
                c.Resolve<IFsoService>(),
                c.Resolve<IConfigurationProvider>(), 
                p.Named<FilePosition>("position")
                ))
                .As<IVersioningSource<FileItem>>();
            //FileVersioningSource is both IVersioningSource and IFolderBrowserService
            builder.Register((c, p) => (IFolderBrowserService)p.TypedAs<IVersioningSource<FileItem>>())
                .As<IFolderBrowserService>();
            builder.Register(c => new FsoService())
                .As<IFsoService>()
                .SingleInstance();
            builder.Register((c, p) =>
                                 {
                                     var source =
                                         c.Resolve<IVersioningSource<FileItem>>(new[]
                                                                                    {
                                                                                        new NamedParameter("path",
                                                                                        p.Named<string>("sourcePath")),
                                                                                        new NamedParameter("position",
                                                                                        FilePosition.Master)
                                                                                    });
                                     var target =
                                         c.Resolve<IVersioningSource<FileItem>>(new[]
                                                                                    {
                                                                                        new NamedParameter("path",
                                                                                        p.Named<string>("targetPath")),
                                                                                        new NamedParameter("position",
                                                                                        FilePosition.Slave)
                                                                                    });
                                     return new CheckOutService(
                                         source, target, (IFolderBrowserService) source,
                                         c.Resolve<IMetadataService<FileItem>>(p),
                                         c.Resolve<IConfigurationProvider>(p),
                                         c.Resolve<IFsoService>(p),
                                         p.TypedAs<ILog>()
                                         );
                                 });
            builder.Register((c, p) => new PvmlMetadataService(p.Named<string>("sourcePath"), p.TypedAs<ILog>())).As<IMetadataService<FileItem>>();
            builder.RegisterModule(new LogInjectionModule());
            builder.Register((c, p) => new CheckoutForm(p.TypedAs<ILog>()));
            builder.Register((c, p) =>
                                 {
                                     var vs = c.Resolve<IVersioningSource<FileItem>>(p.Union(new[]
                                                                                                 {
                                                                                                     new NamedParameter("position",
                                                                                                         FilePosition.Slave),
                                                                                                     new NamedParameter("path",
                                                                                                         p.Named<string>("sourcePath"))
                                                                                                 }));
                                     var conf = c.Resolve<IDiffApplicationService<FileItem>>(p);
                                     return new CheckInService(vs, (IFolderBrowserService) vs,
                                                        c.Resolve<IMetadataService<FileItem>>(p),
                                                        c.Resolve<IConfigurationProvider>(),
                                                        p.TypedAs<ILog>(), c.Resolve<IDiffService<FileItem>>(p),
                                                        Container.Instance,
                                                        conf, (IConflictResolutionService<FileItem>) conf
                                         );
                                 });
            builder.Register((c, p) => new DiffApplicationService(
                                           c.Resolve<IFsoService>(), c.Resolve<ISourceControlService>(p),
                                           p.TypedAs<ILog>()
                                           )).As<IDiffApplicationService<FileItem>>();
            builder.Register(
                (c, p) => (IConflictResolutionService<FileItem>) c.Resolve<IDiffApplicationService<FileItem>>(p))
                .As<IConflictResolutionService<FileItem>>();
            builder.Register((c, p) => new DiffService()).As<IDiffService<FileItem>>();
            builder.Register((c, p) => new SourceControlCmdService(p.TypedAs<ILog>(), p.Named<string>("tfsConfigPath"))).As<ISourceControlService>();
            builder.Register((c, p) => new CheckInForm(p.TypedAs<ILog>(), c.Resolve<IConfigurationProvider>()));
            builder.Register((c, p) => new PendingChanges());
            return builder.Build();
        }
    }
}
